package maumau;

import java.util.*;

public class MauMau_Game {

    private static final int nPlayer = 4;
    private Random rand;
    private Vector<Integer> drawCards;  // Stapel aus dem Karten abgehoben werden
    private Vector<Integer> deckCards;  // Abgelegte Karten
    private int topCardCol;
    private int topCardMult;
    private MauMau_Intf player[];
    private MauMau_State state[];

    MauMau_Game(MauMau_Intf[] p) {
        player = p;
        state = new MauMau_State[4];
        deckCards = new Vector<Integer>();
        rand = new Random();
    }

    ;

    Integer drawCard() {
        if (drawCards.size() == 0) {
            while (deckCards.size() > 1) {
                int n = deckCards.size() - 2;
                int i = (n == 0 ? 0 : rand.nextInt(n));
                drawCards.add(deckCards.get(i));
                deckCards.remove(i);
            }
        }

        if (drawCards.size() == 0) {
            return -1;
        }

        int c = drawCards.get(0);
        drawCards.remove(0);
        return c;
    }

    Integer getTopCard() {
        return deckCards.get(deckCards.size() - 1);
    }

    private Vector<Integer> getActions(MauMau_State s) {
        Vector<Integer> v = new Vector<Integer>();
        for (int c = 0; c < s.getNrCards(); c++) {
            int card = s.getCard(c);
            int typ = s.getCardType(card);
            int col = s.getCardColor(card);
            if (s.getCardType(getTopCard()) == MauMau_Constants.SIEBEN && topCardMult > 0) {
                if (typ == MauMau_Constants.SIEBEN) {
                    v.add(card);
                }
            } else if (typ == MauMau_Constants.BUBE) {
                for (int t = 0; t < 4; t++) {
                    v.add(MauMau_Constants.BUBE_BASE + t + col * 4);
                }
            } else if (typ == s.getCardType(getTopCard()) || col == topCardCol) {
                v.add(card);
            }
        }

        if (s.getCardType(getTopCard()) == MauMau_Constants.SIEBEN && topCardMult > 0) {
            v.add(MauMau_Constants.TAKE_TWO);
        } else {
            v.add(MauMau_Constants.TAKE_ONE);
        }

        return v;
    }

    private MauMau_State performAction(MauMau_State s, Integer a) {

        Vector<Integer> cs = s.getAllCards();
        if (a == MauMau_Constants.TAKE_ONE) {
            int c = drawCard();
            if (c >= 0) {
                cs.add(c);
            }
        } else if (a == MauMau_Constants.TAKE_TWO) {
            for (int t = 0; t < 2 * topCardMult; t++) {
                int c = drawCard();
                if (c >= 0) {
                    cs.add(c);
                }
            }
            topCardMult = 0;
        } else if (a <= 31) {
            for (int i = 0; i < cs.size(); i++) {
                if (cs.get(i) == a) {
                    if ((a / 4) == MauMau_Constants.SIEBEN && (getTopCard() / 4) == MauMau_Constants.SIEBEN) {
                        topCardMult++;
                    }

                    int c = cs.get(i);
                    deckCards.add(c);
                    topCardCol = c % 4;
                    cs.remove(i);
                    break;
                }
            }
        } else if (a >= MauMau_Constants.BUBE_BASE && a <= MauMau_Constants.BUBE_END) {
            int c = ((a / 4) % 4) + MauMau_Constants.BUBE * 4;
            for (int i = 0; i < cs.size(); i++) {
                if (cs.get(i) == c) {
                    deckCards.add(cs.get(i));
                    cs.remove(i);
                    topCardCol = a % 4;
                    break;
                }
            }
        } else {
            System.out.println("Ooops. Illegale Aktion");
            System.out.println(1 / 0);
        }


        MauMau_State result = new MauMau_State(cs);
        return result;
    }

    public void play(int game) {
        int current_player = game % nPlayer;

        // Shuffle cards
        Vector<Integer> cardstmp = new Vector<Integer>();
        for (int t = 0; t < 32; t++) {
            cardstmp.add(t);
        }
        drawCards = new Vector<Integer>();
        while (cardstmp.isEmpty() == false) {
            int r = rand.nextInt(cardstmp.size());
            drawCards.add(cardstmp.remove(r));
        }
//        System.out.println("Shuffled cards (" + drawCards.size() + ") " + drawCards);

        // Start new game, pass 5 cards to each player
        topCardMult = 1;
        for (int t = 0; t < nPlayer; t++) {
            int np = (t + current_player) % nPlayer;
            player[np].newGame();
            state[np] = new MauMau_State(drawCards.get(0), drawCards.get(1), drawCards.get(2), drawCards.get(3), drawCards.get(4));
            drawCards.remove(0);
            drawCards.remove(0);
            drawCards.remove(0);
            drawCards.remove(0);
            drawCards.remove(0);
        }
        deckCards.add(drawCards.get(0));
        topCardCol = getTopCard() % 4;
        drawCards.remove(0);
        for (int t = 0; t < nPlayer; t++) {
            state[t].setOpenCard(getTopCard(), topCardCol, topCardMult);
            state[t].setNrCardsOponents(5, 5, 5);
        }

        while (true) {

            state[current_player].setOpenCard(getTopCard(), topCardCol, topCardMult);
            state[current_player].setNrCardsOponents(state[(current_player + 1) % 4].getNrCards(), state[(current_player + 2) % 4].getNrCards(), state[(current_player + 3) % 4].getNrCards());

//            System.out.println("*******************************************************");
//            System.out.println(" DrawCard: " + drawCards);
//            System.out.println(" DeckCard: " + deckCards);
//            System.out.println("Player " + (current_player + 1) + " " + player[current_player].getName());
//            state[current_player].print();

            Vector<Integer> actions = getActions(state[current_player]);
//            System.out.println("  Moegliche Aktionen: " + actions);


            Integer a = player[current_player].step(new MauMau_State(state[current_player]), new Vector<Integer>(actions), 0.0, false);
//            System.out.println(" Aktion: " + a);
            state[current_player] = performAction(state[current_player], a);

            // System.out.println("  State nach Action:"); state[current_player].print();

            if (state[current_player].getNrCards() == 0) {
                break;
            }

            // Acht?
            if (state[current_player].getCardType(a) == MauMau_Constants.ACHT) {
                current_player++;
            }

            current_player = (current_player + 1) % nPlayer;
        }

        // Final call
//        System.out.println("##########################################################");
        int totalCards = 0;
        for (int i = 0; i < nPlayer; i++) {
            totalCards += state[i].getNrCards();
        }

        for (int i = 0; i < nPlayer; i++) {
            if (state[i].getNrCards() == 0) {
                player[i].step(new MauMau_State(state[i]), new Vector<Integer>(), totalCards, true);
            } else {
                player[i].step(new MauMau_State(state[i]), new Vector<Integer>(), -state[i].getNrCards(), true);
            }

        }   
    }
}
